﻿using Furion.CMS.Application;
using Furion.CMS.Core;
using Furion.CMS.Domain;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Web.Core.Account
{
    /// <summary>
    /// 移动手机登录处理
    /// </summary>
    [Injection(Named = LoginTypeConsts.Mobile)]
    public class MobileLoginHandler : ILoginHandler, ITransient
    {
        private readonly IRepository<UserInfo> _repository;
        private readonly IDistributedCache<string> _phoneVerifyCode;

        public MobileLoginHandler(IRepository<UserInfo> repository,
            IDistributedCache<string> phoneVerifyCode)
        {
            _repository = repository;
            _phoneVerifyCode = phoneVerifyCode;
        }

        public async Task<UserPassport> VerifyAsync(Dictionary<string, object> fields, UserLoginRecord loginRecord, SiteSetting settings)
        {
            if (fields.TryGetValue(LoginVerifyType.Mobile.AccountField, out object phoneNumber) &&
                fields.TryGetValue(LoginVerifyType.Mobile.PasswordField, out object verifyCode))
            {
                loginRecord.Method = "手机验证码登录";

                var passport = await _repository.AsQueryable(false)
                      .Where(t => t.PhoneNumber.Equals(phoneNumber))
                      .Include(i => i.Passports.Where(t => t.Type == PassportType.Normal))
                      .SelectMany(s => s.Passports)
                      .Include(i=>i.User)
                      .ThenInclude(i => i.Roles)
                      .Include(i => i.User)
                      .ThenInclude(i => i.Organizations)
                      .ThenInclude(i => i.Roles)
                      .AsSplitQuery()
                      .FirstOrDefaultAsync();

                if (passport == null)
                    throw new AccountLoginException(LoginVerifyType.Mobile.ErrorMessage, "手机关联账号不存在");

                if (!_phoneVerifyCode.Get($"captcha_{phoneNumber}")?.Equals(verifyCode) ?? true)
                    throw new AccountLoginException(LoginVerifyType.Mobile.ErrorMessage);

                // 修改日志
                loginRecord.PassportId = passport.Id;
                loginRecord.Account = passport.Account; // 更改账号

                return passport;
            }
            else
            {
                throw new AccountLoginException("参数错误");
            }
        }
    }
}
